﻿//Restriction Module v 1.0
//Written by Bugra POSTACI (c)
//August 2010
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Text.RegularExpressions; 

namespace RestrictionModuleApp
{
    [Serializable]
    public class RestrictionRule
    {
        public RestrictionRule()
        {
            _Expressions = new List<Expression>();
        }

        #region Privates
       
        private bool _ContinueRuleList = false; //Default false ;
        private List<Expression> _Expressions;
        private string _RedirectURL;
        private string _Audiences;
        private bool _Enabled;
        private RestrictionAction _Action;
        private RestrictionModes _Mode;
        List<string> _AudienceList = null; //used for internal purpose
        private Regex _RegularExpression; //used for internal purpose
        #endregion

        #region Properties
        

        /// <summary>
        /// This generic list contains expressions for this rule
        /// </summary>
        [XmlArray]
        public List<Expression> Expressions
        {
            get { return _Expressions; }
            set { _Expressions = value; }
        }
       
        /// <summary>
        /// if one of expression match with selected criteria , request will be redirect to this url
        /// </summary>
        public string RedirectURL
        {
            get { return _RedirectURL; }
            set { _RedirectURL = value; }
        }
    
        /// <summary>
        /// Comma seperated values that represent an access list.if it is null means all users.
        /// </summary>
        public string Audiences
        {
            get { return _Audiences; }
            set { _Audiences = value; }
        }

        /// <summary>
        /// Defines this rule is active or inactive.
        /// </summary>
        [XmlAttribute]
        public bool Enabled
        {
            get { return _Enabled; }
            set { _Enabled = value; }
        }

        /// <summary>
        /// if one of expression match with selected criteria, "Allow" means continue request according by audiences ,"Deny" redirect request according by audiences
        /// </summary>
        [XmlAttribute]
        public RestrictionAction Action
        {
            get { return _Action; }
            set { _Action = value; }
        }
        
        /// <summary>
        /// Defines criteria parameter that expression run on it.
        /// </summary>
        [XmlAttribute]
         public RestrictionModes Mode
         {
             get { return _Mode; }
             set { _Mode = value; }
         }

        /// <summary>
        /// This property use that performance criteria for dont compile regex every request.
        /// </summary>
        [XmlIgnore]
        internal Regex RegularExpression
        {
            get { return _RegularExpression; }
            set { _RegularExpression = value; }
        }

        /// <summary>
        /// This property use that performance criteria for find operations for users.
        /// </summary>
        [XmlIgnore]
        internal List<string> AudienceList
        {
            get { return _AudienceList; }
            set { _AudienceList = value; }
        }

        /// <summary>
        /// Use this options for that case of one expression match with criteria and normally exit loop and 
        /// you want to run other rules with in loop than set this propery true. 
        /// </summary>
        [XmlAttribute]
        public bool ContinueRuleList
        {
            get { return _ContinueRuleList; }
            set { _ContinueRuleList = value; }
        }
      

        #endregion

        #region Methods

        /// <summary>
        /// Audit httpcontext current user with Audience list.
        /// </summary>
        /// <returns>Boolean of user found is "true" if not "false"</returns>
        public bool AuthorizeRule()
        {

            //Create Audience List from comma sep. string.
            try
            {
                if (this.AudienceList == null)
                {
                    this.AudienceList = new List<string>();
                    string[] users = this.Audiences.Split(',');
                    foreach (string usr in users)
                    {
                        string s = usr.Trim().ToLower();
                        if(s.Length>0)
                            this.AudienceList.Add(s);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error Parsing Audience");
            }

            //!Important.
            if (AudienceList.Count == 0) return true; //Means Everyone.

            //Check user in list.
            if (HttpContext.Current.User != null)
            {
                string currentUser = HttpContext.Current.User.Identity.Name.ToLower();

                if (this.AudienceList.Contains(currentUser))
                {
                    return true;
                }
            }

            return false;
        }


        /// <summary>
        /// Find and return compare criteria in httpcontext.
        /// </summary>
        /// <returns>Returns compare criteria as string</returns>
        public string GetCompareCriteria()
        {
            switch (this.Mode)
            {
                case RestrictionModes.RequestURL:
                    return HttpContext.Current.Request.Url.ToString();

                case RestrictionModes.RequestContentType:
                    return HttpContext.Current.Request.ContentType;

                case RestrictionModes.RequestUserHostName:
                    return HttpContext.Current.Request.UserHostName;

                case RestrictionModes.RequestUserHostAddress:
                    return HttpContext.Current.Request.UserHostAddress;
                default:
                    throw new Exception("Error in GetCriteria");
            }

        }

        #endregion

        
    }



}